package rifl.meres4.development.step.impl;

import java.util.concurrent.ArrayBlockingQueue;

import rifl.meres4.commons.model.Software;
import rifl.meres4.commons.step.AbstractWorkflowStep;
import rifl.meres4.development.step.IIntegrationStep;

/**
 * Sets the integrated flag to true.
 * Also links the UI Implementation Classes to ImplementationClasses.
 * 
 * @author Mark Czotter
 * @author Miklos Szennai
 * 
 */
public class IntegrationStep extends AbstractWorkflowStep implements IIntegrationStep {

	protected ArrayBlockingQueue<Software> uiInputQueue = new ArrayBlockingQueue<Software>(10);
	
	@Override
	public Software doStep(Software software) {
		software.setIntegrated(true);
		return software;
	}
	
	@Override
	public Software get() throws InterruptedException {
		Software impl = super.get();
		Software ui = uiInputQueue.take();
		return mergeSoftware(impl, ui);
	}
	
	private Software mergeSoftware(Software impl, Software ui) {
		if (impl.getId() != ui.getId()) return null;
		Software s = new Software(impl.getId());
		s.setSystemDesignPlan(impl.getSystemDesignPlan());
		s.setName(impl.getName());
		s.getComponents().addAll(impl.getImplementationComponents());
		s.getComponents().addAll(ui.getUIComponents());
		return s;
	}
	
	@Override
	public synchronized void addToInputQueue(Software software)
			throws InterruptedException {
		if (this.uiInputQueue.contains(software)) {
			notifyMessageListeners(software);
		}
		this.inputQueue.put(software);
	}
	
	@Override
	public void addToUIInputQueue(Software software) throws InterruptedException {
		if (this.inputQueue.contains(software)) {
			notifyMessageListeners(software);
		}
		this.uiInputQueue.put(software);
	}
	
	@Override
	public boolean hasInput() {
		return (!this.inputQueue.isEmpty() && !this.uiInputQueue.isEmpty());
	}
	
}
